# 导入所需的库
import asyncio
from bilibili_api import video, CommentResourceType, Credential
import pandas as pd
import os

# 如果需要设置代理，可以取消以下注释并填写你的代理服务器信息
# from bilibili_api import request_settings
# request_settings.set_proxy("http://your-proxy.com:port")  # 替换为你的代理地址

async def fetch_bilibili_comments(bvid: str, credential: Credential = None, max_count: int = 100):
    """
    异步获取B站视频的评论
    
    参数:
        bvid: B站视频的BV号，例如 "BV1uv411q7Mv"
        credential: 认证信息，如果不需要登录即可查看的评论，可以传None
        max_count: 想要获取的最大评论数量，默认100条
    返回:
        包含评论信息的字典列表
    """
    try:
        # 1. 实例化Video对象
        v = video.Video(bvid=bvid, credential=credential)
        
        # 2. 获取视频的基本信息（主要是为了确认视频存在，并获取aid）
        info = await v.get_info()
        print(f"开始获取视频《{info['title']}》的评论...")
        
        # 3. 获取评论
        comments_data = []
        next_page = 0  # 评论分页参数，初始为0
        
        # 循环获取评论直到达到所需数量或没有更多评论
        while len(comments_data) < max_count:
            # 获取一页评论
            comments = await v.get_comments(
                root=next_page, 
                type_=CommentResourceType.VIDEO, 
                next_=next_page
            )
            
            # 检查是否还有评论
            if not comments['replies']:
                print("没有更多评论了。")
                break
                
            # 处理当前页的评论
            for comment in comments['replies']:
                if len(comments_data) >= max_count:
                    break  # 达到所需数量，退出循环
                    
                comment_info = {
                    'rpid': comment['rpid'],          # 评论ID
                    'user': comment['member']['uname'],  # 用户名
                    'content': comment['content']['message'],  # 评论内容
                    'like': comment['like'],          # 点赞数
                    'ctime': comment['ctime'],        # 评论时间戳
                    'root': comment['root'],          # 根评论ID（如果是回复）
                    'parent': comment['parent']       # 父评论ID（如果是回复）
                }
                comments_data.append(comment_info)
                print(f"已获取 {len(comments_data)} 条评论: {comment_info['user']} - {comment_info['content'][:30]}...")
            
            # 更新下一页参数
            if comments['cursor']['is_end']:
                print("已到达最后一页评论。")
                break
            next_page = comments['cursor']['next']
            
        print(f"评论获取完成，共获取 {len(comments_data)} 条评论。")
        return comments_data
        
    except Exception as e:
        print(f"获取评论时出现错误: {e}")
        return []

def save_comments_to_csv(comments, filename=None):
    """
    将评论列表保存为CSV文件
    
    参数:
        comments: 评论字典列表
        filename: 保存的文件名，如果不指定则自动生成
    """
    if not comments:
        print("没有评论数据可保存。")
        return
        
    # 如果没有指定文件名，则自动生成
    if not filename:
        import time
        timestamp = int(time.time())
        filename = f"bilibili_comments_{timestamp}.csv"
    
    # 使用pandas创建DataFrame并保存为CSV
    df = pd.DataFrame(comments)
    df['ctime'] = pd.to_datetime(df['ctime'], unit='s')  # 转换时间戳为可读格式
    
    # 确保输出目录存在
    os.makedirs('output', exist_ok=True)
    filepath = os.path.join('output', filename)
    
    df.to_csv(filepath, index=False, encoding='utf-8-sig')
    print(f"评论已保存到: {filepath}")

async def main():
    """
    主函数，演示如何使用上述功能
    """
    # 示例：不需要登录即可访问的公开视频评论
    bvid = "BV1uv411q7Mv"  # 替换为你想要爬取的视频BV号
    
    # 如果需要登录后才能查看的评论，请取消以下注释并填写你的认证信息
    # SESSDATA = "你的SESSDATA"
    # BILI_JCT = "你的bili_jct"
    # BUVID3 = "你的buvid3"
    # credential = Credential(sessdata=SESSDATA, bili_jct=BILI_JCT, buvid3=BUVID3)
    
    # 对于公开评论，credential传None
    comments = await fetch_bilibili_comments(bvid, credential=None, max_count=50)
    
    # 保存评论到CSV文件
    if comments:
        save_comments_to_csv(comments, f"comments_{bvid}.csv")

# 运行主函数
if __name__ == "__main__":
    asyncio.run(main())